package com.zxf.appliction.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.json.JSONObject;

import org.apache.log4j.Logger;


import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.BinaryClient.LIST_POSITION;
import sun.security.jgss.LoginConfigImpl;

/**
 * 访问redis操作 : 集群模式
 * 
 * 最好不要同时操作多个Key,除非你确定它们在同一个slots内,否则方法将抛出异常.
 * 
 * @Created by zyj on 2016年12月15日
 * @Package com.demo.cluster.redis
 */
public class ClusterRedisDao implements IRedisDao {
	private Logger logger = Logger.getLogger(ClusterRedisDao.class);
	private JedisCluster client = RedisDatasource.getClient();

	public static void main(String[] args) {
		ClusterRedisDao crd = new ClusterRedisDao();
		System.out.println(crd.LRange("aa", 0l, 3l).size());
	}

	/**
	 * 根据源码注释发现,在cluster模式中,redis集群只计划使用 db0.
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param index
	 * @return
	 * @Version 1.0
	 */
	public boolean changeDB(int index) {
		// client.select(index);
		return false;
	}

	// -------------------------------------------List---------------------------------------------//
	/**
	 * 将一个或多个值 value 插入到列表 key 的 表头!<br>
	 * <br>
	 * 表头!表头!!!!!.<br>
	 * <br>
	 * 如果有多个 value 值，那么各个 value 值按从左到右的顺序依次插入到表头：<br>
	 * 比如说，对空列表 mylist 执行命令 LPUSH mylist a b c ，列表的值将是 c b a ，<br>
	 * 这等同于原子性地执行 LPUSH mylist a 、 LPUSH mylist b 和 LPUSH mylist c 三个命令。
	 * 
	 * 如果 key 不存在，一个空列表会被创建并执行 LPUSH 操作。
	 * 
	 * 当 key 存在但不是列表类型时，打印日志,并返回false;
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param values
	 * @return
	 * @Version 1.0
	 */
	public boolean LPush(String key, String... values) {
		String type = getType(key).toLowerCase();
		if (!"list".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要list,得到" + type, new IllegalArgumentException(type));
			return false;
		}
		// l = lpush后的列表长度
		try {
			long l = client.lpush(key, values);
			if (l > 0)
				return true;
		} catch (Exception e) {
			logger.error("在list头部添加元素失败.", e);

		}
		return false;
	}

	/**
	 * 将一个或多个值 value 插入到列表 key 的 表尾!<br>
	 * <br>
	 * 表尾!表尾!!尾!!!.<br>
	 * <br>
	 * 如果有多个 value 值，那么各个 value 值按从左到右的顺序依次插入到表尾：
	 * 
	 * 比如对一个空列表 mylist 执行 RPUSH mylist a b c ，得出的结果列表为 a b c ，
	 * 
	 * 等同于执行命令 RPUSH mylist a 、 RPUSH mylist b 、 RPUSH mylist c 。
	 * 
	 * 如果 key 不存在，一个空列表会被创建并执行 LPUSH 操作。
	 * 
	 * 当 key 存在但不是列表类型时，打印日志,并返回false;
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param values
	 * @return
	 * @Version 1.0
	 */
	public boolean RPush(String key, String... values) {
		String type = getType(key).toLowerCase();
		if (!"list".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要list,得到" + type, new IllegalArgumentException(type));
			return false;
		}
		// l = rpush后的列表长度
		try {
			long l = client.lpush(key, values);
			if (l > 0)
				return true;
		} catch (Exception e) {
			logger.error("在list尾部添加元素失败.", e);

		}
		return false;
	}

	/**
	 * 将值 value 插入到列表 key 当中，位于值 pivot 之前
	 * 
	 * 当 pivot 不存在于列表 key 时，不执行任何操作。
	 * 
	 * 当 key 不存在时， key 被视为空列表，不执行任何操作。
	 * 
	 * 如果 key 不是列表类型，打印一个异常,并返回false;
	 * 
	 * 
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param pivot
	 * @param value
	 * @return
	 * @Version 1.0
	 */
	public boolean LInsertBefore(String key, String pivot, String value) {
		String type = getType(key).toLowerCase();
		if (!"list".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要list,得到" + type, new IllegalArgumentException(type));
			return false;
		}
		try {
			long l = client.linsert(key, LIST_POSITION.BEFORE, pivot, value);
		} catch (Exception e) {
			logger.error("list插入数据失败", e);
			return false;

		}
		return true;
	}

	/**
	 * 将值 value 插入到列表 key 当中，位于值 pivot 之后
	 * 
	 * 当 pivot 不存在于列表 key 时，不执行任何操作。
	 * 
	 * 当 key 不存在时， key 被视为空列表，不执行任何操作。
	 * 
	 * 如果 key 不是列表类型，打印一个异常,并返回false;
	 * 
	 * 
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param pivot
	 * @param value
	 * @return
	 * @Version 1.0
	 */
	public boolean LInsertAfter(String key, String pivot, String value) {
		String type = getType(key).toLowerCase();
		if (!"list".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要list,得到" + type, new IllegalArgumentException(type));
			return false;
		}
		try {
			long l = client.linsert(key, LIST_POSITION.AFTER, pivot, value);
		} catch (Exception e) {
			logger.error("list插入数据失败", e);
			return false;

		}
		return true;
	}

	/**
	 * 返回列表 key 中，下标为 index 的元素。
	 * 
	 * 下标(index)参数 start 和 stop 都以 0 为底，也就是说，以 0 表示列表的第一个元素，以 1 表示列表的第二个元素，以此类推。
	 * 
	 * 你也可以使用负数下标，以 -1 表示列表的最后一个元素， -2 表示列表的倒数第二个元素，以此类推。
	 * 
	 * 如果 key 不是列表类型，打印异常信息并返回null;
	 * 
	 * 如果 index 参数的值不在列表的区间范围内(out of range)，返回 null
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param index
	 * @return
	 * @Version 1.0
	 */
	public String LIndex(String key, Integer index) {
		String type = getType(key).toLowerCase();
		if (!"list".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要list,得到" + type, new IllegalArgumentException(type));
			return null;
		}
		String result = "";
		try {
			result = client.lindex(key, Long.valueOf(index));
			return result;
		} catch (Exception e) {
			logger.error("获取key中index的元素失败.", e);

		}
		return null;
	}

	/**
	 * 返回列表 key 的长度。
	 * 
	 * 如果 key 不存在，则 key 被解释为一个空列表，返回 0 .
	 * 
	 * 如果 key 不是列表类型，输入错误信息,返回-1
	 * 
	 * 其他异常,返回-1
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @return
	 * @Version 1.0
	 */
	public Long LLength(String key) {
		String type = getType(key).toLowerCase();
		if (!"list".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要list,得到" + type, new IllegalArgumentException(type));
			return -1l;
		}
		try {
			long len = client.llen(key);
			return len;
		} catch (Exception e) {
			logger.error("获取list长度失败.", e);
		}
		return -1l;
	}

	/**
	 * 移除并返回列表 key 的头元素。
	 * 
	 * 当 key 不存在时，返回 null 。
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @return
	 * @Version 1.0
	 */
	public String LPop(String key) {
		String type = getType(key).toLowerCase();
		if (!"list".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要list,得到" + type, new IllegalArgumentException(type));
			return null;
		}
		try {
			String result = client.lpop(key);
			return result;
		} catch (Exception e) {
			logger.error("LPOP方法执行失败.", e);
		}
		return null;
	}

	/**
	 * 返回列表 key 中指定区间内的元素，区间以偏移量 start 和 stop 指定。<br>
	 * 
	 * 下标(index)参数 start 和 stop 都以 0 为底，也就是说，<br>
	 * 
	 * list 的第一个元素的 index 为 0 .
	 * 
	 * 注意LRANGE命令和编程语言区间函数的区别, 假如你有一个包含一百个元素的列表，<br>
	 * 
	 * 对该列表执行 LRANGE list 0 10 ，结果是一个包含11个元素的列表，<br>
	 * 
	 * 这表明 stop 下标也在 LRANGE 命令的取值范围之内(闭区间) .<br>
	 * 
	 * 超出范围的下标 超出范围的下标值不会引起错误。<br>
	 * 
	 * 如果 start 下标比列表的最大下标 end ( LLEN list 减去 1 )还要大，那么 LRANGE 返回一个空列表。<br>
	 * 
	 * 如果 stop 下标比 end 下标还要大，Redis将 stop 的值设置为 end 。<br>
	 * 
	 * 
	 * 如果 Key 不是 一个list或其他异常,则返回null;
	 * 
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param start
	 *            起始位置
	 * @param end
	 *            结束位置
	 * @return
	 * @Version 1.0
	 */
	public List<String> LRange(String key, Long start, Long end) {
		String type = getType(key).toLowerCase();
		if (!"list".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要list,得到" + type, new IllegalArgumentException(type));
			return null;
		}
		List<String> resultList = new ArrayList<>();
		try {
			resultList = client.lrange(key, start, end);
			return resultList;
		} catch (Exception e) {
			logger.error("", e);
		}
		return null;
	}

	/**
	 * 根据参数 count 的值，移除列表中与参数 value 相等的元素。返回被移除元素的数量.<br>
	 * 
	 * 因为不存在的 key 被视作空表(empty list)，所以当 key 不存在时， 总是返回 0 。<br>
	 * 
	 * 当 key 不是一个list类型或其他异常,返回-1<br>
	 * 
	 * <h3>count 的值可以是以下几种：</h3>
	 * <ul>
	 * <li>count > 0 : 从表头开始向表尾搜索，移除与 value 相等的元素，数量为 count 。</li>
	 * 
	 * <li>count < 0 : 从表尾开始向表头搜索，移除与 value 相等的元素，数量为 count 的绝对值。</li>
	 * 
	 * <li>count = 0 : 移除表中所有与 value 相等的值。</li>
	 * </ul>
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param count
	 * @param value
	 * @return
	 * @Version 1.0
	 */
	public Long LRemove(String key, Integer count, String value) {
		String type = getType(key).toLowerCase();
		if (!"list".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要list,得到" + type, new IllegalArgumentException(type));
			return -1l;
		}
		long num = 0;
		try {
			num = client.lrem(key, count, value);
			return num;
		} catch (Exception e) {
			logger.error("list移除元素失败.", e);
		}
		return -1l;
	}

	/**
	 * 将列表 key 下标为 index 的元素的值设置为 value 。
	 * 
	 * 当 index 参数超出范围，或对一个空列表( key 不存在)进行 LSET 时，返回false
	 * 
	 * 当 key 不是一个list时,返回false;
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param index
	 * @param value
	 * @return
	 * @Version 1.0
	 */
	public boolean LSet(String key, Long index, String value) {
		String type = getType(key).toLowerCase();
		if (!"list".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要list,得到" + type, new IllegalArgumentException(type));
			return false;
		}
		try {
			String result = client.lset(key, index, value);
			if ("ok".equals(result.toLowerCase())) {
				return true;
			}
		} catch (Exception e) {
			logger.error("修改list中元素值失败.", e);
		}
		return false;
	}

	// ---------------------------------------------------Set-----------------------------------------------------//
	/**
	 * 判断 member 元素是否集合 key 的成员。<br>
	 * 如果 member 元素不是集合的成员，或 key 不存在，返回 false;<br>
	 * 如果key类型错误,打印错误日志,并返回false;
	 * 
	 * 
	 * @Created by zyj on 2016年12月5日
	 * @param key
	 * @param member
	 * @return
	 * @Version 1.0
	 */
	public boolean Sismember(String key, String member) {
		String type = getType(key).toLowerCase();
		if (!"set".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要set,得到" + type, new IllegalArgumentException(type));
			return false;
		}

		try {
			boolean b = client.sismember(key, member);
			return b;
		} catch (Exception e) {
			logger.error(e);
			return false;

		}
	}

	/**
	 * 移除集合 key 中的一个或多个 member 元素，不存在的 member 元素会被忽略。<br>
	 * 当 key 不是集合类型，打印错误日志,并返回false
	 * 
	 * 
	 * @Created by zyj on 2016年12月5日
	 * @param key
	 *            setKey
	 * @param smembers
	 *            元素
	 * @return
	 * @Version 1.0
	 */
	public boolean SRemove(String key, String... members) {
		String type = getType(key).toLowerCase();
		if (!"set".equals(type) && !"none".equals(type)) {
			// 不是set类型
			logger.error("key类型错误,需要set,得到" + type, new IllegalArgumentException(type));
			return false;
		}
		long result = 0l;

		try {
			result = client.srem(key, members);

			if (result > 0) {
				return true;
			}
		} catch (Exception e) {
			logger.error("移除set中元素失败.", e);

		}
		return false;
	}

	/**
	 * 获取set集合<br>
	 * 返回集合 key 中的所有成员。<br>
	 * 不存在的 key 被视为空集合。<br>
	 * Key不是一个set类型时,返回null;<br>
	 * 其他错误返回null;
	 * 
	 * @param key
	 * @return
	 */
	public Set<String> SMembers(String key) {

		String type = getType(key).toLowerCase();
		if (!"set".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要set,得到" + type, new IllegalArgumentException(type));
			return null;
		}

		Set<String> backout = new HashSet<>();
		try {
			backout = client.smembers(key);
		} catch (Exception e) {
			logger.error("读取Set集合失败", e);
			return null;

		}
		return backout;
	}

	/**
	 * 设置set集合<br>
	 * 将一个或多个 member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略。<br>
	 * 假如 key 不存在，则创建一个只包含 member 元素作成员的集合。<br>
	 * 当 key 不是集合类型时，打印错误,并返回false;
	 * 
	 * @param key
	 * @param members
	 *            元素数组
	 * @param ttlSeconds
	 *            生存时间,设置为null或为-1时表示不设置
	 * @return
	 */
	public boolean SAdd(String key, Integer ttlSeconds, String... members) {

		Long l = 0L;
		String type = getType(key).toLowerCase();
		if (!"set".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要set,得到" + type, new IllegalArgumentException(type));
			return false;
		}

		try {
			l = client.sadd(key, members);
			if (ttlSeconds != null && ttlSeconds != -1) {
				client.expire(key, ttlSeconds);
			}
			return true;
		} catch (Exception e) {
			logger.error("设置set失败", e);
			return false;

		}
	}

	// ------------------------------------------Hash-------------------------------------------//

	/**
	 * 删除哈希表 key 中的一个或多个指定域，不存在的域将被忽略。<br>
	 * 如果key的类型不是hash,则打印日志,返回false;
	 * 
	 * 
	 * @Created by zyj on 2016年12月5日
	 * @param key
	 * @param fields
	 * @return
	 * @Version 1.0
	 */
	public boolean HDel(String key, String... fields) {

		String type = getType(key).toLowerCase();
		if (!"hash".equals(type) && !"none".equals(type)) {
			logger.error("key类型错误,需要hash,得到" + type, new IllegalArgumentException(type));
			return false;
		}

		// l = 被删除的key的数量,不包含忽略的key
		try {
			Long l = client.hdel(key, fields);
			if (l == 0) {
				logger.error("警告,被删除的key值为0,可能是所有field均不存在,也有可能发生错误.", new Exception(String.valueOf(l)));
			}
		} catch (Exception e) {
			logger.error("删除hash域出现错误", e);
			return false;

		}
		return true;
	}

	/**
	 * 获取HashMap<br>
	 * 类型不是hash时打印错误信息,返回null<br>
	 * key不存在返回 {}
	 * 
	 * 
	 * @param key
	 * @return
	 */
	public Map HGetAll(String key) {

		String type = getType(key).toLowerCase();
		if (!"hash".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要hash,得到的为" + type, new IllegalArgumentException(type));
			return null;
		}
		try {
			Map map = client.hgetAll(key);
			if (map != null) {
				return map;
			}
		} catch (Exception e) {
			logger.error("读取Hash内容失败", e);

		}
		return null;
	}

	/**
	 * 读取HashMap中的一个字段<br>
	 * key必须为Hash类型,否则打印异常返回null<br>
	 * 读取异常时,返回null
	 * 
	 * @param key
	 * @param fieldName
	 * @return
	 */
	public String HMGetSingleField(String key, String fieldName) {

		String result = "";
		String type = getType(key).toLowerCase();
		// key 存在 但是不是hash类型
		if (!"hash".equals(type) && !"none".equals(type)) {
			logger.error("Key的类型错误,需要hash,得到的是" + type, new IllegalArgumentException(type));
			return null;
		}

		try {
			result = client.hget(key, fieldName);
		} catch (Exception e) {
			logger.error("读取Hash域失败.", e);
			return null;

		}
		return result;
	}

	/**
	 * 获取hashmap中的多个字段的值,返回json对象. 异常返回null<br>
	 * 如果key不存在返回空的json对象<br>
	 * 若hash中不存在给出的 fieldName ,则在返回的json对象中不包含该key <br>
	 * e.g. fieldNames = ["f1","f2","f4"]; 其中f4不存在,结果 = {"f1":"v1","f2":"v2"}
	 * 
	 * @param key
	 * @param fieldNames
	 * @return
	 */
	public JSONObject HMGetMultValue(String key, String... fieldNames) throws ArrayIndexOutOfBoundsException {

		String type = getType(key).toLowerCase();
		// Key存在但不是hash , none代表key不存在
		if (!"hash".equals(type) && !"none".equals(type)) {
			logger.error("key的类型错误,需要key为hash类型或key不存在,但得到的是key存在但是类型为:" + type, new Exception());
			return null;
		}
		try {
			List<String> list = client.hmget(key, fieldNames);
			if (list != null) {
				JSONObject obj = new JSONObject();
				for (int i = 0; i < fieldNames.length; i++) {
					obj.put(fieldNames[i], list.get(i));
				}
				return obj;
			}
		} catch (Exception e) {
			logger.error("获取Hash多个字段错误", e);

		}
		return null;
	}

	/**
	 * 设置map的多个字段<br>
	 * 
	 * 
	 * @param key
	 * @param ttlSeconds
	 *            生存时间
	 * @param fieldAndValue
	 *            数组形式 两个为一对, e.g. ['field1','value1','field2','value2'.....]
	 * @return
	 */
	public boolean HMSetMultField(String key, Integer ttlSeconds, String... fieldAndValue) {

		if (isExists(key)) {
			String type = getType(key).toLowerCase();
			if (!"hash".equals(type)) {
				logger.error("Key已经存在,但是不是hash类型不能使用HMSet方法设置值.", new Exception(type));
				return false;
			}
		}

		Map<String, String> map = new HashMap<>();
		// fieldAndValue 不能为空
		if (fieldAndValue != null && fieldAndValue.length != 0 && fieldAndValue.length % 2 != 0) {
			logger.error("数组长度必须为偶数:" + fieldAndValue, new ArrayIndexOutOfBoundsException());
			return false;
		}
		for (int i = 0; i < fieldAndValue.length; i++) {
			map.put(fieldAndValue[i], fieldAndValue[i + 1]);
			i++;
		}
		return HMSet(key, map, ttlSeconds);
	}

	/**
	 * 将哈希表 key 中的域 field 的值设为 value 。 <br>
	 * 如果 key 不存在，一个新的哈希表被创建并进行 HSET 操作。<br>
	 * 如果域field 已经存在于哈希表中，旧值将被覆盖.<br>
	 * 当Key的类型不是一个Hash时,将输出错误日志,并返回false
	 * 
	 * @param key
	 *            hash的Key值
	 * @param fieldName
	 *            域的名字
	 * @param fieldValue
	 *            域的值
	 * @return
	 */
	public boolean HMSetSingleField(String key, String fieldName, String fieldValue) {

		String type = getType(key).toLowerCase();
		// none表示key不存在
		if (!"hash".equals(type) && !"none".equals(type)) {
			logger.error("设置hash域失败,key的类型错误,需要key的类型为hash,得到的类型为:" + type, new Exception(type));
			return false;
		}
		try {
			client.hset(key, fieldName, fieldValue);
		} catch (Exception e) {
			logger.error("方法setHMapSingleField()好像抛出了一个未知异常.", e);
			return false;

		}
		return true;
	}

	/**
	 * 设置HashMap,设置控制将打印异常信息,并返回false,
	 * 
	 * 如果hash中已经包含了给出的值,那么新的值将覆盖他.
	 * 
	 * 如果key已经存在,但是不是一个hash类型,则返回false,并打印错误日志信息
	 * 
	 * @param key
	 * @param value
	 *            不可以为null或者为空
	 * @param ttlSeconds
	 *            过期时间 给出null或者 -1 表示不过期
	 * @return
	 */
	public boolean HMSet(String key, Map value, Integer ttlSeconds) {

		if (isExists(key)) {
			String type = getType(key).toLowerCase();
			if (!"hash".equals(type)) {
				logger.error("Key已经存在,但是不是hash类型不能使用HMSet方法设置值.", new Exception(type));
				return false;
			}
		}

		if (value == null || value.isEmpty()) {
			logger.error("设置的Map为空,redis不允许所设置的map为空", new Exception("Map is empty"));
			return false;
		}
		try {
			String ok = client.hmset(key, value);
			if ("OK".equals(ok)) {
				if (ttlSeconds != null && ttlSeconds != -1) {
					// 设置过期时间 默认不过期
					client.expire(key, ttlSeconds);
				}
				return true;
			}
		} catch (Exception e) {
			logger.error("设置Hash值失败", e);

		}
		return false;
	}

	/**
	 * 判断Hash类型key中是否含有@fieldName字段<br>
	 * 
	 * 
	 * @param key
	 *            类型必须为Hash,否则抛出异常
	 * @param fieldName
	 * @return
	 * @throws IllegalArgumentException
	 */
	public boolean HashExists(String key, String fieldName) throws IllegalArgumentException {

		String type = getType(key).toLowerCase();
		if (!"hash".equals(type) && !"none".equals(type)) {
			IllegalArgumentException e = new IllegalArgumentException("参数类型错误,要求Key的类型必须为Hash类型!");
			logger.error("", e);
			throw e;
		}

		try {
			if (isExists(key)) { // 先判断key存在否
				return client.hexists(key, fieldName);
			}
		} catch (Exception e) {
			// TODO: handle exception
			logger.error("判断Hash域是否存在失败.", e);

		}
		return false;
	}

	// -----------------------------------------String------------------------------------------//
	/**
	 * 仅用于获取redis中String类型数据,redis中key不存在时返回null,<br>
	 * 当key的value值类型不为String时返回空,并在日志中打印错误信息
	 * 
	 * @param key
	 * @return 返回一个指定key的value值,当value不为String类型时打印异常信息并返回null,当key不存在时返回null
	 */
	public String getString(String key) {

		String value = "";

		String type = getType(key).toLowerCase();
		if (!"string".equals(type) && !"none".equals(type)) {
			logger.error("得到Key的类型不是一个String类型, Key is a " + type);
			return null;
		}
		try {
			// 异常返回null
			value = client.get(key);
		} catch (Exception e) {
			logger.error("设置String类型value值错误", e);
			return null;

		}
		return value;
	}

	/**
	 * 设置String类型值,value的长度不能超过 1073741824 字节(1GB).
	 * 
	 * @param key
	 * @param value
	 * @param ttlSeconds
	 *            设置过期时间,设置为null或-1表示不设置
	 * @return
	 */
	public boolean setString(String key, String value, Integer ttlSeconds) {

		System.out.println(client.getClusterNodes());
		String code = "";
		try {
			code = client.set(key, value);
			if ("OK".equals(code)) {
				if (ttlSeconds != null && ttlSeconds != -1) {
					client.expire(key, ttlSeconds);
				}
				// success
				return true;
			}
		} catch (Exception e) {
			logger.error("异常方法:setKey(String,String,Integer),设置Key值失败.", e);

		}

		return false;
	}

	// -----------------------------------Key------------------------------- //

	/**
	 * 删除给定的一个或多个 key 。<br>
	 * 不存在的 key 会被忽略。<br>
	 * 异常时返回false;
	 * 
	 * 最好不要多个一起删除,除非你确定他们在同一个slots内,否则将抛出异常.
	 * 
	 * @Created by zyj on 2016年12月5日
	 * @param keys
	 * @return
	 * @Version 1.0
	 */
	public boolean Del(String... keys) {
		try {
			Long l = client.del(keys);
		} catch (Exception e) {
			logger.error("delKey()方法删除Key时,发生了一个异常", e);
			return false;

		}
		return true;
	}

	/**
	 * 获取Key的类型 , 异常返回空
	 * 
	 * @Created by zyj on 2016年12月5日
	 * @param key
	 * @return
	 * @Version 1.0
	 */
	public String getType(String key) {
		try {
			String type = client.type(key);
			return type;
		} catch (Exception e) {
			logger.error("获取key类型失败.", e);
			return "";

		}
	}

	/**
	 * 判断Key是否存在
	 * 
	 * 错误时打印异常日志,返回false
	 * 
	 * @param key
	 * @return
	 */
	public boolean isExists(String key) {
		try {
			boolean isExists = client.exists(key);
			return isExists;
		} catch (Exception e) {
			logger.error("无法判断key是否存在.", e);
			return false;

		}

	}

	/**
	 * 设置key生存时间,单位秒
	 * 
	 * 发生异常打印异常信息,返回false;
	 * 
	 * @param key
	 * @param seconds
	 * @return
	 */
	public boolean Expire(String key, Integer seconds) {
		try {
			Long l = client.expire(key, seconds);
			if (l > 0) {
				return true;
			}
		} catch (Exception e) {
			logger.error("设置key的生存时间失败.", e);
		}
		return false;
	}

	/**
	 * 设置key永不过期
	 * 
	 * 发生异常打印异常日志,返回false;
	 * 
	 * @param key
	 * @return
	 */
	public boolean Persist(String key) {

		try {
			Long l = client.persist(key);
			if (l > 0) {
				return true;
			}
		} catch (Exception e) {
			logger.error("无法设置key永不过期.", e);
		}
		return false;
	}

}
